import {FileInfo, FileType} from "@shared/models/FileInfo";
import {BBYUtils} from "@shared/utils/BBYUtils";
import {StatusCode} from "@shared/models/StatusCode";
import {DirectLinkResult} from "@shared/models/DirectLinkResult";
import {DiskPageStatus} from "@core/service/page/DiskPageStatus";
import {DiskService, FileOptionReq, SearchReq} from "@core/service/DiskService";
import {NzMessageService} from "ng-zorro-antd/message";
import {ActivatedRoute, Params, Router} from "@angular/router";
import {FavoriteActionReq, UserActionService} from "@core/service/UserActionService";
import {NzContextMenuService, NzDropdownMenuComponent} from "ng-zorro-antd/dropdown";
import {InputDialogContent} from "@/app/pages/common/input-dialog-content";
import {EditPermissionDialogContent} from "@/app/pages/disk/file-list/file-options/edit-permission-dialog-content";
import {MkdirDialogContent} from "@/app/pages/disk/file-list/file-options/mkdir-dialog-content";
import {Observable} from "rxjs";
import {Result} from "@shared/models/Result";
import {api} from "@core/service/config/api";
import {TextEditorComponent} from "@/app/pages/disk/file-list/text-editor/text-editor.component";
import {NzModalService} from "ng-zorro-antd/modal";
import {FileUploadService} from "@core/service/FileUploadService";
import {NzImageService} from "ng-zorro-antd/image";
import {ClipboardService} from "@core/service/ClipboardService";
import {PermissionRequest} from "@/app/pages/disk/file-list/file-options/permission-request";
import {PermissionDetail} from "@shared/models/Permission";
import {AuthService} from "@core/service/AuthService";
import {PmMessage} from "@shared/models/PmMessage";
import {AddFavoriteDialog} from "@/app/pages/disk/file/add-favorite-dialog";
import {Favorite} from "@shared/models/UserInfo";
import {OfflineDialog} from "@/app/pages/disk/offline-dialog";



export class PageService {
  private _pageStatus: DiskPageStatus = new DiskPageStatus();
  get pageStatus(): DiskPageStatus {
    return this._pageStatus;
  }

  // 用于恢复页面
  openUrl = ''
  openParam: Params | undefined
  rootUrl = 'share/disk'

  constructor(
    protected diskService: DiskService,
    protected userActionService: UserActionService,
    protected message: NzMessageService,
    protected router: Router,
    protected nzContextMenuService: NzContextMenuService,
    protected dialogService: NzModalService,
    protected fileUploadService: FileUploadService,
    protected nzImageService: NzImageService,
    protected clipboardService: ClipboardService
  ) {
  }

  dealUrl(url: string, params: Params) {
    this.openUrl = decodeURI(url)
    this.openParam = params;
  }

  // 只加载列表包屑
  private loadRun(target: string, action: 'id' | 'path') {
    this._pageStatus.loading = true;
    BBYUtils.handelResult(
      this.diskService.loadDir(target, action),
      res => {
        // this._pageStatus.fileIdNameMap.clear()
        if (res.data.parent.owner != this._pageStatus.owner.userId) {
          // 设置owner
          BBYUtils.handelResult(
            this.userActionService.getUserPubInfo(res.data.parent.owner),
            res => {
              this._pageStatus.owner = {
                userId: res.data.userId || '',
                username: res.data.username || '全部文件',
                self:res.data.userId==AuthService.readUserInfo()?.userId
              }
            },
            res => {
              this._pageStatus.owner.username = '所有文件'
            }
          )
        }
        this.dealResult(res.data)
        this._pageStatus.loading = false;
      },
      res => {
        this.message.error(res.msg)
        this._pageStatus.loading = false;
      }
    )
  }

  setBreadcrumb(path: string) {
    let spl = path.split("/")
    if (spl.length == 0) {
      return;
    }
    let breadcrumb: { title: string, link: string }[] = []
    let lk = `/${this.rootUrl}/${spl[0]}/`;
    for (let i = 1; i < spl.length; i++) {
      if (spl[i] === '') continue;
      lk = lk + spl[i]
      breadcrumb.push({title: spl[i], link: lk})
      lk += '/'
    }
    this._pageStatus.search = '';
    // 面包屑
    console.log('breadcrumb', breadcrumb)
    this._pageStatus.breadcrumb = breadcrumb;
    this._pageStatus.open_path = path
    this._pageStatus.checkedFiles = [];
  }

  /**
   * 不为    this._pageStatus.fileList 赋值
   * @param list
   * @protected
   */
  protected dealFileList(list:FileInfo[]){
    let views = new Array<FileInfo>()
    let ids = new Array<string>()
    console.log(list)
    for (let file of list) {
      // this._pageStatus.fileIdNameMap.set(file.id, file.name)
      file.type = BBYUtils.getFileType(file)
      if (file.type == FileType.IMG || file.type == FileType.VIDEO) {
        views.push(file)
        ids.push(file.id)
      }
      let makerName = BBYUtils.userIdNameMap.get(file.maker);
      if (!makerName){
        BBYUtils.userIdNameMap.set(file.maker,file.maker)
        BBYUtils.handelResult(
          this.userActionService.getUserPubInfo(file.maker),
          res => {
            BBYUtils.userIdNameMap.set(file.maker,res.data.username)
          },
          res => {}
        )
      }
    }
    if (views.length==0) return;
    this.diskService.createDownloads(ids)
      .subscribe((res: any) => {
        if (res.code == StatusCode.OK) {
          if (views.length==1){
            views[0].directId=res.data.directId
            return;
          }
          let map = res.data
          views.forEach(file => {
            let directLink: DirectLinkResult | undefined = map[file.id]
            if (directLink) {
              file.directId = directLink.directId
            }
          })
        }
      })

  }
  private dealResult(data: any) {
    if (data.parent) {
      this._pageStatus.currentFile = data.parent
    }
    this._pageStatus.checkedFiles = [];
    this.dealFileList(data.list);
    this._pageStatus.fileList = data.list;

    // 如果是从搜索页面转过来要选择文件
    if (this.openParam?.check){
      let check = this.openParam.check
      let file = this.pageStatus.fileList.find(file=> {
        return file.id == check
      })
      if (file){
        this.onItemChecked(file,true);
      }
    }
  }

  /**
   * 必须带id
   * @param path 格式为：id/dir...
   * @param params 参数
   */
  load(path: string, params: Params) {
    if (!path) {// 没有 path，加载 path
      BBYUtils.handelResult(
        this.diskService.filePath(params.id),
        res => {
          console.log(res)
          this.router.navigate([`${this.rootUrl}/${res.data}`])
        },
        res => {
          this.message.error("文件路径错误！")
        }
      )
      return;
    }

    // 有 path
    this.setBreadcrumb(path)
    if (params.search) {// 搜索
      if (params.id) {
        this.search(params)
      } else {
        this.message.error('当前页不能全局搜索！')
      }
    }else if (params.id) {// 有id，用id打开
      this.loadRun(params.id, 'id')
    } else {// 用路径打开
      this.loadRun(path, 'path')
    }

  }

  // 刷新列表
  flash() {
    this.loadRun(this._pageStatus.currentFile.id, 'id')
  }

  search(params: Params) {
    this._pageStatus.loading = true;
    let data: SearchReq = {
      target: params.id,
      keyword: params.search,
      page: params.page || 1,
      limit: params.limit || 10
    }
    BBYUtils.handelResult(
      this.diskService.search(data),
      res => {
        console.log(res.data)
        // this._pageStatus.fileIdNameMap.clear()
        this.dealResult(res.data)
        this._pageStatus.search = data.keyword;
        this._pageStatus.loading = false;
      },
      res => {
        this.message.error('搜索失败！')
        this._pageStatus.loading = false;
      }
    )
  }


  downloadClick() {
    let that = this;
    if (this.pageStatus.checkedFiles.length > 0) {
      let files = this.getCheckedFiles()
      let names = this.getFileNames(files)
      if (files.length > 1) {
        this.dialogService.create({
          nzTitle: '您选择了多个文件，是否打包下载？',
          nzWidth: '400px', nzCentered: true,
          nzContent: names.toString(),
          nzOnOk: ($event: Event) => {
            console.log('下载 ', names)
            // this.pageStatus.loading=true;
            // this.handleResult('已开始下载',this.diskService.download())
          },
        })
      } else if (files.length == 1) {
        let file = files[0]
        this.diskService.createDownload(file)
          .subscribe((res: any) => {
            console.log(res.msg)
            if (res.code == StatusCode.OK) {
              this.diskService.download(file.id, res.data.directId)
            } else {
              this.message.error(res.msg)
            }
          })
      } else {
        this.message.error("请先选择文件！");
      }
    }

  }

  closeMenu() {
    console.log('----------')
    this.nzContextMenuService.close();
  }

  diskPageContextmenuClick($event: MouseEvent, contextTemplate: NzDropdownMenuComponent) {
    this.nzContextMenuService.create($event, contextTemplate);
  }

  //上传文件
  onUploadFileSelected(event: any) {
    let files = event.target.files;
    if (!files) return;
    let nzContent = "";
    for (let file of files) {
      nzContent += file.name + ' (' + (file.size / 1024 / 1024).toFixed(2) + 'Mb)' + '<hr>'
    }

    let that = this;
    this.dialogService.create({
      nzTitle: "将上传以下文件到 \'" + that.pageStatus.open_path + "\'",
      nzWidth: '400px', nzCentered: true,
      nzContent: nzContent,
      nzOnOk: ($event: Event) => {
        that.fileUploadService.create(files, that.pageStatus.open_path);
        that.fileUploadService.upload_card_show = true
      },
    })
  }


  /***************************************************/

  // 查看文件信息
  detailClick() {
    // todo 最后实现
  }

  // 删除文件
  deleteFileClick() {
    let that = this;
    if (this.pageStatus.checkedFiles.length > 0) {
      let files = this.getCheckedFiles()
      let names = this.getFileNames(files)
      this.dialogService.create({
        nzTitle: '确认要删除以下文件？',
        nzWidth: '400px', nzCentered: true,
        nzContent: names.toString(),
        nzOnOk: ($event: Event) => {
          console.log('delete ', names)
          let data: FileOptionReq = {
            opera: 'delete',
            fileList: files.map(file => {
              return {id: file.id}
            })
          }
          this.pageStatus.loading = true;
          this.handleResult('已删除', this.diskService.fileOption(data))
        },
      })
    } else {
      this.message.error("请先选择文件！");
    }
  }

  //粘贴文件
  pasteClick() {
    if (this.clipboardService.files.length == 0) {
      return
    }
    let type = this.clipboardService.type == 'copy' ? '复制' : '移动';

    this.dialogService.confirm({
      nzTitle: type + '文件',
      nzContent: '确定要' + type + "文件：\n'"
        + this.getFileNames(this.clipboardService.files).toString()
        + "' \n到：" + this.pageStatus.open_path,
      nzOnOk: () => {
        console.log(type, this.clipboardService.files)

        let data: FileOptionReq = {
          opera: this.clipboardService.type == 'copy' ? 'copy' : 'move',
          fileList: this.clipboardService.files.map(file => {
            return {from: file.id, to: this.pageStatus.currentFile.id}
          })
        }
        this.pageStatus.loading = true;
        this.handleResult('复制完成', this.diskService.fileOption(data))
      }
    })
    // 移动完成后清空
    if (this.clipboardService.type == 'cut') {
      this.clipboardService.clear()
    }
    console.log(this.clipboardService.files)
  }

  // 剪贴文件到粘贴板
  cutFileClick() {
    let that = this;
    if (that.pageStatus.checkedFiles.length > 0) {
      this.clipboardService.cut(this.getCheckedFiles())
    } else {
      this.message.error("请先选择文件！此错误不该出现，如遇见，请联系管理员！");
      return
    }
    console.log(this.clipboardService)
  }

  // 复制文件到粘贴板
  copyFileClick() {
    let that = this;
    if (that.pageStatus.checkedFiles.length > 0) {
      this.clipboardService.copy(this.getCheckedFiles())
    } else {
      this.message.error("请先选择文件！此错误不该出现，如遇见，请联系管理员！");
      return
    }
    console.log(this.clipboardService);
    console.log(this.pageStatus.open_path)
  }

  // 重命名
  renameFileClick() {
    let files = this.getCheckedFiles();
    if (files.length == 0) {//没选文件，修改目录权限
      this.message.error("请选择单个文件！此错误不该出现，如遇见，请联系管理员！")
      return;
    }
    let file = BBYUtils.clone(files[0]);
    this.dialogService.create({
      nzTitle: '重命名-' + file.name,
      nzContent: InputDialogContent,
      nzComponentParams: {
        value: file.name
      },
      nzOnOk: (page) => {
        console.log(page.value)
        let data: FileOptionReq = {
          opera: 'rename',
          fileList: [{
            id: file.id,
            newName: page.value
          }]
        }
        this.pageStatus.loading = true;
        this.handleResult("修改成功", this.diskService.fileOption(data))
      }
    })

  }

  //修改权限
  ediePermissionClick() {
    let files = this.getCheckedFiles();
    let file: FileInfo | undefined;
    if (files.length == 0) {//没选文件，修改目录权限
      if (this.pageStatus.currentFile) {
        files.push(this.pageStatus.currentFile)
      }
    }
    file = BBYUtils.clone(files[0]);
    if (!file) return
    let names = this.getFileNames(files)
    console.log('准备修改权限：', file)
    this.dialogService.create({
      nzTitle: '修改权限-' + file.name,
      nzContent: EditPermissionDialogContent,
      nzComponentParams: {
        file,
        names
      },
      nzOnOk: (page) => new Promise(
        resolve => {
          let data = {
            ids: files.map(file => file.id),
            permission: page.file.permission
          }
          BBYUtils.handelResult(
            this.diskService.editPermission(data),
            res => {
              for (let f of files) {
                f.permission = file?.permission
              }
              resolve()
              this.message.success("权限修改完成!");
            },
            res => {
              resolve()
              this.message.error(res.msg)
            }
          )
        })
    })
  }

  // 新建文件夹
  mkDirClick() {
    let file = new FileInfo()
    file.parent = this.pageStatus.currentFile.id
    this.dialogService.create({
      nzTitle: '新建文件夹',
      nzContent: MkdirDialogContent,
      nzComponentParams: {
        file
      },
      nzOnOk: (page) => new Promise(resolve => {
        BBYUtils.handelResult(
          this.diskService.mkdir(page.file),
          res => {
            this.message.success('创建完成')
            let file = res.data as FileInfo
            file.type = FileType.DIR
            this.pageStatus.fileList.push(file)
            resolve()
          },
          res => {
            this.message.error(res.msg)
            resolve()
          }
        )
      })
    })
  }

  handleResult(success: string, obv: Observable<Result>) {
    obv.subscribe((res) => {
      console.log(res)
      this.pageStatus.loading = false;
      if (res.code == StatusCode.OK) {
        if (success) {
          this.message.success(success);
        }
        this.flash()
      } else if (res.code == StatusCode.PART_FINISHED) {
        this.message.error('完成了部分任务！')
      } else {
        let error: Map<string, string> = res.data;
        // this.message.error(error.)
        // this.message.error('全部失败！')
        // this.dialogService.error({
        //   nzTitle:'全部任务错误！',
        //   nzContent:
        // })


      }
    }, er => {
      this.pageStatus.loading = false;
      this.message.error('网络连接失败！')
    })
  }

  /**************/

  //双击选择文件
  fileDoubleClick(file: FileInfo) {
    if (!file.isFile) {
      let url = `/${this.rootUrl}/${this.pageStatus.open_path}/${file.name}`
      this.router.navigate([url], {queryParams: {'id': file.id}});
      // this.loadDir(this.pageStatus.open_path + (this.pageStatus.open_path.endsWith('/')?'':'/') + rowItem.name);
      // let url = `/${this.pageName}/${${(this.pageStatus.open_path.endsWith('/') ? '' : '/')}${file.name}`
      // this.router.navigate([url],{queryParams:{'id':file.id}});
      return;
    }
    let type = BBYUtils.getFileType(file);
    switch (type) {
      case FileType.VIDEO:
        if (file.directId) {
          window.open(`/file/video?fileId=${file.id}&directId=${file.directId}`)
          return;
        }
        BBYUtils.handelResult(
          this.diskService.createDownload(file),
          res => {
            window.open(`/file/video?fileId=${file.id}&directId=${res.data.directId}`)
          },
          res => {
            if (res.code == StatusCode.FILE_NEED_PASS){
              this.askPass((resolve,pass) => {
                BBYUtils.handelResult(
                  this.diskService.createDownload(file,pass),
                  res => {
                    window.open(`/file/video?fileId=${file.id}&directId=${res.data.directId}`)
                  },
                  res => {
                    this.message.error(res.msg)
                  }
                )
                resolve()
              })
            }
            this.message.error(res.msg)
          }
        )
        break;
      case FileType.IMG:
        if (file.directId) {
          const images = [
            {
              src: `${api.imgView}/${file.id}?directId=${file.directId}`,
              alt: 'ng-zorro'
            }
          ];
          this.nzImageService.preview(images, {nzZoom: 1, nzRotate: 0})
          return;
        }
        BBYUtils.handelResult(
          this.diskService.createDownload(file),
          res => {
            console.log(`${api.imgView}/${file.id}?directId=${res.data.directId}`)
            const images = [
              {
                src: `${api.imgView}/${file.id}?directId=${res.data.directId}`,
                alt: 'ng-zorro'
              }
            ];
            this.nzImageService.preview(images, {nzZoom: 1, nzRotate: 0})
          },
          res => {
            this.message.error(res.msg)
          }
        )
        break;
      case FileType.TEXT:
        BBYUtils.handelResult(
          this.diskService.createDownload(file),
          res => {
            file.directId = res.data.directId;
            BBYUtils.handelResult(
              this.diskService.viewText(file),
              res => {
                this.dialogService.create({
                  nzTitle: file.name,
                  nzWidth: "700px",
                  nzBodyStyle: {'padding': '5px', 'background-color': '#f1f1f1'},
                  nzContent: TextEditorComponent,
                  nzComponentParams: {
                    text: res.data
                  },
                  nzClosable: false,
                  nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000))
                });
              },
              res => {
                this.message.error('加载失败！')
              }
            )
          },
          res => {
            this.message.error(res.msg)
          }
        )
        break;
    }

  }

  //文件单击右键
  contextMenu($event: MouseEvent, contextTemplate: NzDropdownMenuComponent, file: FileInfo) {
    if (!file.checked) {
      this.onAllChecked(false);
    }
    this.onItemChecked(file, true);
    this.nzContextMenuService.create($event, contextTemplate);
  }

  onAllChecked(checked: boolean): void {
    this.pageStatus.fileList.forEach((item) => item.checked = checked);
    this.refreshCheckedStatus();
  }

  refreshCheckedStatus(): void {
    this.pageStatus.all_checked = this.pageStatus.fileList.every((item) => item.checked);
    let cnt = 0;
    this.pageStatus.checkedFiles = this.getCheckedFiles()
  }

  onItemChecked(file: FileInfo, checked: boolean): void {
    file.checked = checked;
    this.refreshCheckedStatus();
    if (this.pageStatus.checkedFiles.length == 1) {

    }
  }

  getFileNames(files: FileInfo[]) {
    return files.map(file => file.name)
  }

  // getNamesByIds(ids: string[]) {
  //   return ids.map(id => this.pageStatus.fileIdNameMap.get(id))
  // }

  // 获取被选择的文件
  getCheckedFiles() {
    return Array.from(this.pageStatus.fileList.filter(item => item.checked).values())
  }

  getImgURL(file: FileInfo) {
    return BBYUtils.getTypeImg(file);
  }

  searchClick() {
    if (this.pageStatus.searchInputValue == '' || !this.pageStatus.searchInputValue) {
      return;
    }
    let url = `/${this.rootUrl}/${this.pageStatus.open_path}`
    let file = this.pageStatus.currentFile
    this.router.navigate([url], {
      queryParams: {
        'search': this.pageStatus.searchInputValue,
        'id': file.id
      }
    });
  }

  reqFilePmClick() {
    let files = this.getCheckedFiles();
    let file: FileInfo | undefined;
    if (files.length == 0) {
      files.push(this.pageStatus.currentFile)
    }
    file = files[0]

    let names: string[] = []
    let ids = files.map(file => {
      names.push(file.name)
      return file.id
    })
    let detail = BBYUtils.getPermissionDetail(file);
    if (detail){
      detail = BBYUtils.clone(detail);
    }
    if (!detail) {
      detail = new PermissionDetail()
    }
    let fileInfo = AuthService.readUserInfo();
    let data: PmMessage = {
      date: '', fromName: fileInfo?.username || '',
      from: fileInfo?.userId || '', to: file.owner,
      detail, fileIds: ids,
      id: '', message: ''
    }
    console.log(data)
    this.dialogService.create({
        nzTitle: `请求文件权限`,
        nzContent: PermissionRequest,
        nzOkText: '发送',
        nzComponentParams: {
          detail, isFile: file.isFile, names
        },
        nzOnOk: (page) =>
          new Promise(resolve => {
            data.message = page.message
            BBYUtils.handelResult(
              this.diskService.addPmMessage(data),
              res => {
                this.message.success('添加成功！')
              },
              res => {
                this.message.error(res.msg)
              }
            )
            resolve()
          })
      }
    )
  }

  addToFavorite() {
    if (this.pageStatus.checkedFiles.length!=1){
      return;
    }
    let groups = AuthService.getFavorites()
    if (!groups){
      this.message.error('数据错误，请刷新页面！')
      return;
    }
    let file=this.pageStatus.checkedFiles[0]
    this.dialogService.create({
      nzTitle:'添加收藏',
      nzContent:AddFavoriteDialog,
      nzComponentParams:{
        groups,
        favoriteName:file.name
      },
      nzOnOk:page=>
        new Promise((resolve,reject) => {
          let data:FavoriteActionReq= {
            opera:'addFav',
            fileId:file.id,groupId:page.groupId,
            newName:page.favoriteName
          }
          BBYUtils.handelResult(
            this.userActionService.setFavorites(data),
            res => {
              AuthService.saveFavorites(res.data)
              this.message.success('添加收藏成功！')
              resolve()
            },
            res => {
              this.message.error(res.msg)
              reject()
            }
          )
      })
    })
  }

  createOfflineClick() {
    let currentFile = this.pageStatus.currentFile
    console.log(currentFile)
    if (!currentFile||!currentFile.id){
      this.message.error('此处不能上传文件！')
      return;
    }
    let path=this.pageStatus.open_path;
    path = path.replace(currentFile.owner,this.pageStatus.owner.username)
    this.dialogService.create({
      nzTitle:'添加离线任务',
      nzContent:OfflineDialog,
      nzComponentParams:{
        path
      },
      nzOnOk:(page) =>
        this.fileUploadService.addOffline(currentFile.id,page.url)
    })
  }
  askPass(call: (resolve:any,pass:string) => void) {
    this.dialogService.create({
      nzTitle:'该文件需要密码',
      nzContent:InputDialogContent,
      nzComponentParams:{
        placeholder:'请输入文件密码'
      },
      nzOnOk:(page)=>new Promise((resolve,reject) => {
        if (page.value)
          call(resolve,page.value)
        else{
          this.message.error('请输入密码！')
          reject();
        }
      })
    })
  }
}
